home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pinstaller / templates / x86ArchitectureTemplate.py < prev   
Text File  |  2006-02-15  |  32KB  |  690 lines

  1. """
  2. # Copyright 1999-2005 Gentoo Foundation
  3. # This source code is distributed under the terms of version 2 of the GNU
  4. # General Public License as published by the Free Software Foundation, a copy
  5. # of which can be found in the main directory of this project.
  6. Gentoo Linux Installer
  7.  
  8. $Id: x86ArchitectureTemplate.py,v 1.101 2006/02/13 00:24:49 agaffney Exp $
  9. Copyright 2004 Gentoo Technologies Inc.
  10.  
  11.  
  12. This fills in x86 specific functions.
  13. """
  14.  
  15. import GLIUtility, string, time
  16. from GLIArchitectureTemplate import ArchitectureTemplate
  17. from GLIException import *
  18. import parted
  19. import GLIStorageDevice
  20.         
  21. MEGABYTE = 1024 * 1024
  22.  
  23. class x86ArchitectureTemplate(ArchitectureTemplate):
  24.     def __init__(self,configuration=None, install_profile=None, client_controller=None):
  25.         ArchitectureTemplate.__init__(self, configuration, install_profile, client_controller)
  26.         self._architecture_name = 'x86'
  27.         self._kernel_bzimage = "arch/i386/boot/bzImage"
  28.  
  29.     def install_bootloader(self):
  30.         "Installs and configures bootloader"
  31.         #
  32.         # THIS IS ARCHITECTURE DEPENDANT!!!
  33.         # This is the x86 way.. it uses grub
  34.  
  35.         bootloader_pkg = self._install_profile.get_boot_loader_pkg()
  36.  
  37.         # first install bootloader
  38.         if bootloader_pkg and bootloader_pkg.lower() != "none":
  39.             exitstatus = self._portage.emerge(bootloader_pkg)
  40. #            if not GLIUtility.exitsuccess(exitstatus):
  41. #                raise GLIException("BootLoaderEmergeError", 'fatal', 'install_bootloader', "Could not emerge bootloader!")
  42. #            else:
  43.             self._logger.log("Emerged the selected bootloader.")
  44.         
  45.         # now configure said bootloader
  46.         # null boot-loader first
  47.         if bootloader_pkg.lower() == "none":
  48.             return
  49.         elif "grub" in bootloader_pkg: # this catches 'grub-static' as well as '=sys-boot/grub-0.95*'
  50.             self._configure_grub()
  51.         elif "lilo" in bootloader_pkg:
  52.             self._configure_lilo()
  53.         # probably should add in some more bootloaders
  54.         # dvhtool, raincoat, netboot, gnu-efi, cromwell, syslinux, psoload
  55.         else:
  56.             raise GLIException("BootLoaderError",'fatal','install_bootloader',"Don't know how to configure this bootloader: "+bootloader_pkg)
  57.         
  58.     def _sectors_to_megabytes(self, sectors, sector_bytes=512):
  59.         return float((float(sectors) * sector_bytes)/ float(MEGABYTE))
  60.  
  61.     def _add_partition(self, disk, start, end, type, fs):
  62.         types = { 'primary': parted.PARTITION_PRIMARY, 'extended': parted.PARTITION_EXTENDED, 'logical': parted.PARTITION_LOGICAL }
  63.         fsTypes = {}
  64.         fs_type = parted.file_system_type_get_next ()
  65.         while fs_type:
  66.             fsTypes[fs_type.name] = fs_type
  67.             fs_type = parted.file_system_type_get_next (fs_type)
  68.         fstype = None
  69.         if fs: fstype = fsTypes[fs]
  70.         newpart = disk.partition_new(types[type], fstype, start, end)
  71.         constraint = disk.dev.constraint_any()
  72.         disk.add_partition(newpart, constraint)
  73.  
  74.     def partition(self):
  75.         parts_old = {}
  76.         tmp_parts_new = self._install_profile.get_partition_tables()
  77.         parts_new = {}
  78.         for device in tmp_parts_new:
  79.             parts_new[device] = tmp_parts_new[device].get_install_profile_structure()
  80.         detected_devices = GLIStorageDevice.detect_devices()
  81.         for device in detected_devices:
  82.             tmpdevice = GLIStorageDevice.Device(device)
  83.             tmpdevice.set_partitions_from_disk()
  84.             parts_old[device] = tmpdevice.get_install_profile_structure()
  85.  
  86.         self.notify_frontend("progress", (0, "Examining partitioning data"))
  87.         total_steps = float(len(parts_new) * 3)
  88.         cur_progress = 0
  89.         for device in parts_new.keys():
  90.             # Skip this device in parts_new if device isn't detected on current system
  91.             if not device in detected_devices:
  92.                 self._logger.log("There is no physical device " + device + " detected to match the entry in the install profile...skipping")
  93.                 continue
  94.  
  95.             # Check to see if the old and new partition table structures are the same
  96.             table_changed = 0
  97.             for part in parts_new[device]:
  98.                 if not part in parts_old[device]:
  99.                     table_changed = 1
  100.                     break
  101.                 oldpart = parts_old[device][part]
  102.                 newpart = parts_new[device][part]
  103.                 if oldpart['type'] == newpart['type'] and oldpart['start'] == newpart['start'] and oldpart['end'] == newpart['end'] and newpart['format'] == False:
  104.                     continue
  105.                 else:
  106.                     table_changed = 1
  107.                     break
  108.             # Skip this device if they are they same
  109.             if not table_changed:
  110.                 self._logger.log("Partition table for " + device + " is unchanged...skipping")
  111.                 continue
  112.  
  113.             self._logger.log("partitioning: Processing " + device + "...")
  114.  
  115.             # Create pyparted objects for this device
  116.             parted_dev = parted.PedDevice.get(device)
  117.             try:
  118.                 parted_disk = parted.PedDisk.new(parted_dev)
  119.             except:
  120.                 parted_disk = parted_dev.disk_new_fresh(parted.disk_type_get((tmp_parts_new[device].get_disklabel() or GLIStorageDevice.archinfo[self._architecture_name]['disklabel'])))
  121.             new_part_list = parts_new[device].keys()
  122.             new_part_list.sort()
  123.             device_sectors = parted_dev.length
  124.  
  125.             # Iterate through new partitions and check for 'origminor' and 'format' == False
  126.             for part in parts_new[device].keys():
  127.                 tmppart_new = parts_new[device][part]
  128.                 if not tmppart_new['origminor'] or tmppart_new['format']: continue
  129.                 tmppart_old = parts_old[device][tmppart_new['origminor']]
  130.                 parted_part = parted_disk.get_partition(tmppart_new['origminor'])
  131.                 # This partition in parts_new corresponds with an existing partitions, so we save the start/end sector and flags
  132.                 for flag in range(0, 10):
  133.                     # The 10 is completely arbitrary. If flags seem to be missed, this number should be increased
  134.                     if not parted_part: break
  135.                     if parted_part.is_flag_available(flag) and parted_part.get_flag(flag):
  136.                         if not "flags" in tmppart_new: tmppart_new['flags'] = []
  137.                         tmppart_new['flags'].append(flag)
  138.                 if tmppart_new['resized']:
  139.                     self._logger.log("  Partition " + str(part) + " has oldminor " + str(tmppart_new['oldminor']) + " and it being resized...saving start sector " + str(parted_part.geom.start))
  140.                     tmppart_new['start'] = parted_part.geom.start
  141.                     tmppart_new['end'] = 0
  142.                 else:
  143.                     self._logger.log("  Partition " + str(part) + " has origminor " + str(tmppart_new['origminor']) + "...saving start sector " + str(parted_part.geom.start) + " and end sector " + str(parted_part.geom.end))
  144.                     tmppart_new['start'] = parted_part.geom.start
  145.                     tmppart_new['end'] = parted_part.geom.end
  146.  
  147. #            if parts_new[dev][parts_new[dev].keys()[0]]['mb']:
  148. #                # Change MB/%/* into sectors
  149. #                total_sectors = parted_dev.length
  150. #                sector_size = parted_dev.sector_size
  151. #                total_mb = float(total_sectors * sector_size) / MEGABYTE
  152. #                start_sector = 0
  153. #                mb_left = total_mb
  154. #                for part in parts_new[dev]:
  155. #                    tmppart = parts_new[dev][part]
  156. #                    if tmppart['type'] == "extended": continue
  157. #                    if tmppart['mb'][-1] == "%":
  158. #                        tmppart['mb'] = float(tmppart['mb'][:-1]) / 100 * total_mb
  159. #                    mb_left = mb_left - float(tmppart['mb'])
  160. #                partlist = parts_new.keys()
  161. #                partlist.sort()
  162. #                for part in partlist:
  163. #                    if part > 4: continue
  164. #                    tmppart = parts_new[dev][part]
  165. #                    if tmppart['type'] == "extended":
  166. #                        for part_log in partlist:
  167. #                            if part < 5: continue
  168. #                            tmppart_log = parts_new[dev][part_log]
  169. #                            if not tmppart['start']:
  170. #                                tmppart['start'] = start_sector
  171. #                            if tmppart_log['mb'] == "*":
  172. #                                tmppart_log['mb'] = mb_left
  173. #                            part_bytes = long(tmppart_log['mb'] * MEGABYTE)
  174. #                            part_sectors = round(part_bytes / sector_size)
  175. #                            tmppart_log['start'] = start_sector
  176. #                            tmppart_log['end'] = start_sector + part_sectors - 1
  177. #                            tmppart['end'] = tmppart_log['end']
  178. #                            start_sector = start_sector + part_sectors
  179. #                        continue
  180. #                    if tmppart['mb'] == "*":
  181. #                        tmppart['mb'] = mb_left
  182. #                    part_bytes = long(tmppart['mb'] * MEGABYTE)
  183. #                    part_sectors = round(part_bytes / sector_size)
  184. #                    tmppart['start'] = start_sector
  185. #                    tmppart['end'] = start_sector + part_sectors - 1
  186. #                    start_sector = start_sector + part_sectors
  187. #            else:
  188.  
  189.             # First pass to delete old partitions that aren't resized
  190.             self.notify_frontend("progress", (cur_progress / total_steps, "Deleting partitioning that aren't being resized for " + device))
  191.             cur_progress += 1
  192.             for part in parts_old[device]:
  193.                 oldpart = parts_old[device][part]
  194.                 # Replace 'x86' with call function to get arch from CC
  195.                 if (GLIStorageDevice.archinfo['x86']['extended'] and part > 4) or oldpart['type'] == "free": continue
  196.                 delete = 0
  197.                 if oldpart['type'] == "extended":
  198.                     logical_to_resize = 0
  199.                     for part_log in parts_old[device]:
  200.                         if part_log < 5 or parts_old[device][part_log]['type'] == "free": continue
  201.                         delete_log = 0
  202.                         for new_part in parts_new[device]:
  203.                             if new_part < 5: continue
  204.                             tmppart = parts_new[device][new_part]
  205.                             # This partition is unchanged in the new layout
  206.                             if tmppart['origminor'] == part_log and tmppart['start'] and tmppart['end']:
  207.                                 self._logger.log("  Deleting old minor " + str(part_log) + " to be recreated later")
  208.                                 try:
  209.                                     parted_disk.delete_partition(parted_disk.get_partition(part_log))
  210.                                 except:
  211.                                     self._logger.log("    Could not delete partition...ignoring")
  212.                                 break
  213.                             # This partition is resized with the data preserved in the new layout
  214.                             if tmppart['origminor'] == part_log and tmppart['resized'] and tmppart['start'] and not tmppart['end']:
  215.                                 self._logger.log("  Ignoring old minor " + str(part_log) + " to resize later")
  216.                                 logical_to_resize = 1
  217.                                 break
  218.                     if not logical_to_resize:
  219.                         self._logger.log("  Deleting extended partition with minor " + str(part))
  220.                         parted_disk.delete_partition(parted_disk.get_partition(part))
  221.                     continue
  222.                 for new_part in parts_new[device]:
  223.                     tmppart = parts_new[device][new_part]
  224.                     if tmppart['origminor'] == part and tmppart['start'] and tmppart['end']:
  225.                         self._logger.log("  Deleting old minor " + str(part) + " to be recreated later")
  226.                         try:
  227.                             parted_disk.delete_partition(parted_disk.get_partition(part))
  228.                         except:
  229.                             self._logger.log("    Could not delete partition...ignoring")
  230.                         break
  231.                     if tmppart['origminor'] == part and tmppart['start'] and not tmppart['end']:
  232.                         self._logger.log("  Ignoring old minor " + str(part) + " to resize later")
  233.                         break
  234.             parted_disk.commit()
  235.  
  236.             # Second pass to resize old partitions that need to be resized
  237.             self._logger.log("Partitioning: Second pass...")
  238.             self.notify_frontend("progress", (cur_progress / total_steps, "Resizing remaining partitions for " + device))
  239.             cur_progress += 1
  240.             for part in parts_old[device]:
  241.                 oldpart = parts_old[device][part]
  242.                 for new_part in parts_new[device]:
  243.                     tmppart = parts_new[device][new_part]
  244.                     if tmppart['origminor'] == part and tmppart['resized'] and tmppart['start'] and not tmppart['end']:
  245.                         self._logger.log("  Resizing old minor " + str(part) + " from " + str(oldpart['start']) + "-" + str(oldpart['end'])+  " to " + str(tmppart['start']) + "-" + str(tmppart['end']))
  246.                         type = tmppart['type']
  247.                         minor = part
  248.                         start = tmppart['start']
  249.                         # Replace 512 with code to retrieve bytes per sector for device
  250.                         end = start + (long(tmppart['mb']) * MEGABYTE / 512)
  251.                         for i in new_part_list:
  252.                             if i <= new_part: continue
  253.                             if parts_new[device][i]['start'] and end >= parts_new[device][i]['start']:
  254.                                 end = parts_new[device][i]['start'] - 1
  255.                             elif end >= device_sectors:
  256.                                 end = device_sectors - 1
  257.                             break
  258.                         if type == "ext2" or type == "ext3":
  259.                             total_sectors = end - start + 1
  260.                             ret = GLIUtility.spawn("resize2fs " + device + str(minor) + " " + str(total_sectors) + "s")
  261.                             if ret: # Resize error
  262.                                 raise GLIException("PartitionResizeError", 'fatal', 'partition', "could not resize " + device + str(minor))
  263.                         elif type == "ntfs":
  264.                             total_sectors = end - start + 1
  265.                             total_bytes = long(total_sectors) * 512
  266.                             ret = GLIUtility.spawn("ntfsresize --size " + str(total_bytes) + " " + device + str(minor))
  267.                             if ret: # Resize error
  268.                                 raise GLIException("PartitionResizeError", 'fatal', 'partition', "could not resize " + device + str(minor))
  269.                         elif type == "linux-swap" or type == "fat32" or type == "fat16":
  270.                             parted_fs = parted_disk.get_partition(part).geom.file_system_open()
  271.                             resize_constraint = parted_fs.get_resize_constraint()
  272.                             if end < (start + resize_constraint.min_size) or start != resize_constraint.start_range.start:
  273.                                 raise GLIException("PartitionError", 'fatal', 'partition', "New size specified for " + device + str(minor) + " is not within allowed boundaries")
  274.                             new_geom = resize_constraint.start_range.duplicate()
  275.                             new_geom.set_start(start)
  276.                             new_geom.set_end(end)
  277.                             try:
  278.                                 parted_fs.resize(new_geom)
  279.                             except:
  280.                                 raise GLIException("PartitionResizeError", 'fatal', 'partition', "could not resize " + device + str(minor))
  281.                         self._logger.log("  Deleting old minor " + str(part) + " to be recreated in 3rd pass")
  282.                         parted_disk.delete_partition(parted_disk.get_partition(part))
  283.                         break
  284.             parted_disk.delete_all()
  285.             parted_disk.commit()
  286.  
  287.             # Third pass to create new partition table
  288.             self._logger.log("Partitioning: Third pass....creating partitions")
  289.             self.notify_frontend("progress", (cur_progress / total_steps, "Recreating partition table for " + device))
  290.             cur_progress += 1
  291.             start = 0
  292.             end = 0
  293.             extended_start = 0
  294.             extended_end = 0
  295.             self._logger.log("  Drive has " + str(device_sectors) + " sectors")
  296. #            for part in parts_new[device]:
  297.             for part in new_part_list:
  298.                 newpart = parts_new[device][part]
  299.                 self._logger.log("  Partition " + str(part) + " has " + str(newpart['mb']) + "MB")
  300.                 if newpart['start']:
  301.                     self._logger.log("    Old start sector " + str(newpart['start']) + " retrieved")
  302.                     if start != newpart['start']:
  303.                         self._logger.log("    Retrieved start sector is not the same as the calculated next start sector")
  304.                     start = newpart['start']
  305.                 else:
  306.                     self._logger.log("    Start sector calculated to be " + str(start))
  307.                 if newpart['end']:
  308.                     self._logger.log("    Old end sector " + str(newpart['end']) + " retrieved")
  309.                     end = newpart['end']
  310.                     part_sectors = end - start + 1
  311.                 else:
  312.                     part_sectors = long(newpart['mb']) * MEGABYTE / 512
  313.                     end = start + part_sectors
  314.                     self._logger.log("    End sector calculated to be " + str(end))
  315.                 # Make sure end doesn't overlap next partition's existing start sector
  316.                 for i in new_part_list:
  317.                     if i <= part: continue
  318.                     if parts_new[device][i]['start'] and end >= parts_new[device][i]['start']:
  319.                         if not newpart['type'] == "extended" or i <= 4:
  320.                             end = parts_new[device][i]['start'] - 1
  321.                     break
  322.                 # cap to end of device
  323.                 if end >= device_sectors:
  324.                     end = device_sectors - 1
  325.                 # now the actual creation
  326.                 if newpart['type'] == "free":
  327.                     # Nothing to be done for this type
  328.                     pass
  329.                 elif newpart['type'] == "extended":
  330.                     self._logger.log("  Adding extended partition " + str(part) + " from " + str(start) + " to " + str(end))
  331.                     self._add_partition(parted_disk, start, end, "extended", "")
  332.                     extended_start = start
  333.                     extended_end = end
  334.                 elif part < 5 or not GLIStorageDevice.archinfo['x86']['extended']:
  335.                     self._logger.log("  Adding primary partition " + str(part) + " from " + str(start) + " to " + str(end))
  336.                     self._add_partition(parted_disk, start, end, "primary", newpart['type'])
  337.                 elif GLIStorageDevice.archinfo['x86']['extended'] and part > 4:
  338.                     if start >= extended_end:
  339.                         start = extended_start + 1
  340.                         end = start + part_sectors
  341.                     if part == new_part_list[-1] and end > extended_end:
  342.                         end = extended_end
  343.                     self._logger.log("  Adding logical partition " + str(part) + " from " + str(start) + " to " + str(end))
  344.                     self._add_partition(parted_disk, start, end, "logical", newpart['type'])
  345.                 if "flags" in newpart:
  346.                     for flag in newpart['flags']:
  347.                         if parted_disk.get_partition(part).is_flag_available(flag):
  348.                             parted_disk.get_partition(part).set_flag(flag, True)
  349.                 # write to disk
  350.                 parted_disk.commit()
  351.  
  352.                 # force rescan of partition table
  353.                 # Should not be needed with current stuff
  354.                 #ret = GLIUtility.spawn("partprobe "+device, logfile=self._compile_logfile, append_log=True)
  355.                 
  356.                 # now format the partition
  357.                 # extended and 'free' partitions should never be formatted
  358.                 if newpart['format'] and newpart['type'] not in ('extended', 'free'):
  359.                     devnode = device + str(int(part))
  360.                     errormsg = "could't create %s filesystem on %s" % (newpart['type'],devnode)
  361.                     # if you need a special command and
  362.                     # some base options, place it here.
  363.                     if newpart['type'] == 'linux-swap':
  364.                         cmdname = 'mkswap'
  365.                     elif newpart['type'] == 'fat16':
  366.                         cmdname = 'mkfs.vfat -F 16'
  367.                     elif newpart['type'] == 'fat32':
  368.                         cmdname = 'mkfs.vfat -F 32'
  369.                     elif newpart['type'] == 'ntfs':
  370.                         cmdname = 'mkntfs'
  371.                     # All of these types need a -f as they
  372.                     # ask for confirmation of format
  373.                     elif newpart['type'] in ('xfs','jfs','reiserfs'):
  374.                         cmdname = 'mkfs.%s -f' % (newpart['type'])
  375.                     # add common partition stuff here
  376.                     elif newpart['type'] in ('ext2','ext3'):
  377.                         cmdname = 'mkfs.%s' % (newpart['type'])
  378.                     else: # this should catch everything else
  379.                         raise GLIException("PartitionFormatError", 'fatal', 'partition',"Unknown partition type "+newpart['type'])
  380.  
  381.                     # force a stat of the device so that it
  382.                     # is created on demand. (At least if I
  383.                     # recall how udev works... - robbat2).
  384.                     # sleep a bit first
  385.                     time.sleep(1)
  386.                     # now sleep until it exists
  387. #                    while not GLIUtility.is_file(devnode):
  388. #                        self._logger.log("Waiting for device node "+devnode+" to exist...")
  389. #                        time.sleep(1)
  390.                     # one bit of extra sleep is needed, as there is a blip still
  391. #                    time.sleep(1)
  392.  
  393.                     tries = 0
  394.                     while tries <= 10:
  395.                         # now the actual command
  396.                         cmd = "%s %s %s" % (cmdname,newpart['mkfsopts'],devnode)
  397.                         self._logger.log("  Formatting partition %s as %s with: %s" % (str(part),newpart['type'],cmd))
  398.                         # If logging is not done, then you get errors:
  399.                         # PartitionFormatError :FATAL: partition: could't create ext2 filesystem on /dev/hda1
  400.                         #if GLIUtility.spawn(cmd):
  401.                         #if GLIUtility.spawn(cmd,append_log=True,logfile='/var/log/install-mkfs.log'):
  402.                         ret = GLIUtility.spawn(cmd, logfile=self._compile_logfile, append_log=True)
  403.                         if not GLIUtility.exitsuccess(ret):
  404.                             tries += 1
  405.                             self._logger.log("Try %d failed formatting partition %s...waiting 5 seconds" % (tries, devnode))
  406.                             time.sleep(5)
  407.                         else:
  408.                             break
  409.                     if tries == 3:
  410.                         raise GLIException("PartitionFormatError", 'fatal', 'partition', errormsg)
  411.                 start = end + 1
  412.             self.notify_frontend("progress", (cur_progress / total_steps, "Done with partitioning for " + device))
  413. #            cur_progress += 1
  414.  
  415.     def _configure_grub(self):
  416.         self.build_mode = self._install_profile.get_kernel_build_method()
  417.         self._gather_grub_drive_info()
  418.         root = self._chroot_dir
  419.         exitstatus2, kernel_names = GLIUtility.spawn("ls -1 --color=no " + root + "/boot/pentoo", return_output=True)
  420.         self._logger.log("Output of Kernel Names:\n"+kernel_names)
  421.         if not GLIUtility.exitsuccess(exitstatus2):
  422.             raise GLIException("BootloaderError", 'fatal', '_configure_grub', "Error listing the kernels in /boot")
  423.         if self.build_mode == "genkernel" or self._install_profile.get_kernel_source_pkg() == "livecd-kernel":
  424.             exitstatus3, initrd_names = GLIUtility.spawn("ls -1 --color=no " + root + "/boot/pentoo.igz", return_output=True)
  425.             self._logger.log("Output of Initrd Names:\n"+initrd_names)
  426.         if not GLIUtility.exitsuccess(exitstatus3):
  427.             raise GLIException("BootloaderError", 'fatal', '_configure_grub', "Error listing the initrds")
  428.         self._logger.log("Bootloader: the three information gathering commands have been run")
  429.         
  430.         if not kernel_names[0]:
  431.             raise GLIException("BootloaderError", 'fatal', '_configure_grub',"Error: We have no kernel in /boot to put in the grub.conf file!")
  432.             
  433.         #-------------------------------------------------------------
  434.         #OK, now that we have all the info, let's build that grub.conf
  435.         newgrubconf = ""
  436.         newgrubconf += "default 0\ntimeout 30\n"
  437.         if self.foundboot:  #we have a /boot
  438.             newgrubconf += "splashimage=(" + self.grub_boot_drive + "," + self.grub_boot_minor + ")/grub/splash.xpm.gz\n"
  439.         else: #we have / and /boot needs to be included
  440.             newgrubconf += "splashimage=(" + self.grub_boot_drive + "," + self.grub_boot_minor + ")/boot/grub/splash.xpm.gz\n"
  441.         if self._install_profile.get_bootloader_kernel_args(): 
  442.             bootloader_kernel_args = self._install_profile.get_bootloader_kernel_args()
  443.         else: bootloader_kernel_args = ""
  444.  
  445.         kernel_names = map(string.strip, kernel_names.strip().split("\n"))
  446.         initrd_names = map(string.strip, initrd_names.strip().split("\n"))
  447.         grub_kernel_name = kernel_names[-1].split(root)[-1]
  448.         if initrd_names: grub_initrd_name = initrd_names[-1].split(root)[-1]
  449. #        for i in range(len(kernel_names)):
  450. #            grub_kernel_name = kernel_names[i].split(root)[-1]
  451. #        for i in range(len(initrd_names)):  #this should be okay if blank.
  452. #            grub_initrd_name = initrd_names[i].split(root)[-1]
  453.         #i think this means take the last one it finds.. i.e. the newest.
  454.         
  455.         newgrubconf += "title=Pentoo Linux\n"
  456.         newgrubconf += "root (" + self.grub_boot_drive + "," + self.grub_boot_minor + ")\n"
  457.         if self.build_mode != "genkernel" and self._install_profile.get_kernel_source_pkg() != "livecd-kernel":  #using CUSTOM kernel
  458.             if self.foundboot:
  459.                 newgrubconf += "kernel " + grub_kernel_name[5:] + " root="+self.root_device+self.root_minor+"\n"
  460.             else:
  461.                 newgrubconf += "kernel /boot"+ grub_kernel_name[5:] + " root="+self.root_device+self.root_minor+"\n"
  462.         else: #using genkernel so it has an initrd.
  463.             if self.foundboot:
  464.                 newgrubconf += "kernel " + grub_kernel_name[5:] + " root=/dev/ram0 init=/linuxrc ramdisk=8192 real_root="
  465.                 newgrubconf += self.root_device + self.root_minor + " " + bootloader_kernel_args + "\n"
  466.                 newgrubconf += "initrd " + grub_initrd_name[5:] + "\n"
  467.             else:
  468.                 newgrubconf += "kernel /boot" + grub_kernel_name[5:] + " root=/dev/ram0 init=/linuxrc ramdisk=8192 real_root="
  469.                 newgrubconf += self.root_device + self.root_minor + " " + bootloader_kernel_args + "\n"
  470.                 newgrubconf += "initrd /boot" + grub_initrd_name[5:] + "\n"
  471.         
  472.         #now make the grub.conf file
  473.         file_name = root + "/boot/grub/grub.conf"    
  474.         try:
  475.             shutil.move(file_name, file_name + ".OLDdefault")
  476.         except:
  477.             pass
  478.         f = open(file_name, 'w')
  479.         f.writelines(newgrubconf)
  480.         f.close()
  481.         self._logger.log("Grub installed and configured. Contents of grub.conf:\n"+newgrubconf)
  482.         self._logger.log("Grub has not yet been run.  If a normal install, it will now be run.")
  483.         
  484.     def _gather_grub_drive_info(self):
  485.         self.boot_minor = ""
  486.         self.boot_device = ""
  487.         self.root_device = ""
  488.         self.root_minor = ""
  489.         self.mbr_device = ""
  490.         self.grub_root_minor = ""
  491.         self.grub_boot_minor = ""
  492.         self.grub_boot_drive = ""
  493.         self.grub_root_drive = ""
  494.         self.grub_mbr_drive = ""
  495.         minornum = 0
  496.         #Assign root to the root mount point to make lines more readable
  497.         root = self._chroot_dir
  498.  
  499.  
  500.         self.foundboot = False
  501.         parts = self._install_profile.get_partition_tables()
  502.         for device in parts:
  503.             tmp_partitions = parts[device].get_install_profile_structure()
  504.             for partition in tmp_partitions:
  505.                 mountpoint = tmp_partitions[partition]['mountpoint']
  506.                 if (mountpoint == "/boot"):
  507.                     self.foundboot = True
  508.                 if (( (mountpoint == "/") and (not self.foundboot) ) or (mountpoint == "/boot")):
  509.                     self.boot_minor = str(int(tmp_partitions[partition]['minor']))
  510.                     self.grub_boot_minor = str(int(tmp_partitions[partition]['minor']) - 1)
  511.                     self.boot_device = device
  512.                     self.mbr_device = device
  513.                 if mountpoint == "/":
  514.                     self.root_minor = str(int(tmp_partitions[partition]['minor']))
  515.                     self.grub_root_minor = str(int(tmp_partitions[partition]['minor']) - 1)
  516.                     self.root_device = device
  517.         #RESET the boot device if one is stored already
  518.         if self._install_profile.get_boot_device():
  519.             self.mbr_device = self._install_profile.get_boot_device()
  520.             self._logger.log("Found a mbr device: " + self.mbr_device)
  521.         
  522.         self.grub_boot_drive = self._map_device_to_grub_device(self.boot_device)
  523.         self.grub_root_drive = self._map_device_to_grub_device(self.root_device)
  524.         self.grub_mbr_drive = self._map_device_to_grub_device(self.mbr_device)
  525.         
  526.         if (not self.grub_root_drive) or (not self.grub_boot_drive):
  527.             raise GLIException("BootloaderError", 'fatal', '_gather_grub_drive_info',"Couldn't find the drive num in the list from the device.map")
  528.  
  529.     def _configure_lilo(self):
  530.         self.build_mode = self._install_profile.get_kernel_build_method()
  531.         self._gather_lilo_drive_info()
  532.         root = self._chroot_dir
  533.         file_name3 = root + "/boot/kernel_name"
  534.         root = self._chroot_dir
  535.         exitstatus0 = GLIUtility.spawn("ls "+root+"/boot/kernel-* > "+file_name3)
  536.         if (exitstatus0 != 0):
  537.             raise GLIException("BootloaderError", 'fatal', '_configure_lilo', "Could not list kernels in /boot or no kernels found.")
  538.         if self.build_mode == "genkernel" or self._install_profile.get_kernel_source_pkg() == "livecd-kernel":
  539.             exitstatus1 = GLIUtility.spawn("ls "+root+"/boot/init* >> "+file_name3)
  540.             if (exitstatus1 != 0):
  541.                 raise GLIException("BootloaderError", 'fatal', '_configure_lilo', "Could not list initrds in /boot")
  542.         g = open(file_name3)
  543.         kernel_name = g.readlines()
  544.         g.close()
  545.         if not kernel_name[0]:
  546.             raise GLIException("BootloaderError", 'fatal', '_configure_lilo',"Error: We have no kernel in /boot to put in the grub.conf file!")
  547.         kernel_name = map(string.strip, kernel_name)
  548.         kernel_name[0] = kernel_name[0].split(root)[1]
  549.         kernel_name[1] = kernel_name[1].split(root)[1]
  550.         if self._install_profile.get_bootloader_kernel_args(): bootloader_kernel_args = self._install_profile.get_bootloader_kernel_args()
  551.         else: bootloader_kernel_args = ""
  552.         #-------------------------------------------------------------
  553.         #time to build the lilo.conf
  554.         newliloconf = ""
  555.         if self._install_profile.get_boot_loader_mbr():
  556.             newliloconf += "boot="+self.mbr_device+"   # Install LILO in the MBR \n"
  557.         else:
  558.             newliloconf += "boot="+self.boot_device+self.boot_minor+"   # Install LILO in the MBR \n"
  559.         newliloconf += "prompt                    # Give the user the chance to select another section\n"
  560.         newliloconf += "timeout=50                # Wait 5 (five) seconds before booting the default section\n"
  561.         newliloconf += "default=gentoo            # When the timeout has passed, boot the \"gentoo\" section\n"
  562.         newliloconf += "# Only if you use framebuffer. Otherwise remove the following line:\n"
  563.         if not self._install_profile.get_kernel_bootsplash():
  564.             newliloconf += "#"
  565.         newliloconf += "vga=788                   # Framebuffer setting. Adjust to your own will\n"
  566.         newliloconf += "image=/boot"+kernel_name[0][5:]+" \n"
  567.         newliloconf += "  label=gentoo \n  read-only \n"
  568.         if self.build_mode != "genkernel" and self._install_profile.get_kernel_source_pkg() != "livecd-kernel": 
  569.             newliloconf += "  root="+self.root_device+self.root_minor+" \n"
  570.             if bootloader_kernel_args:
  571.                 newliloconf += "  append=\""+bootloader_kernel_args+"\" \n"
  572.         else:
  573.             newliloconf += "  root=/dev/ram0 \n"
  574.             newliloconf += "  append=\"init=/linuxrc ramdisk=8192 real_root="+self.root_device+self.root_minor + " " + bootloader_kernel_args + "\" \n"
  575.             newliloconf += "  initrd=/boot"+kernel_name[1][5:] + "\n\n"
  576.         newliloconf = self._lilo_add_windows(newliloconf)
  577.         #now make the lilo.conf file
  578.         file_name = root + "/etc/lilo.conf"    
  579.         try:
  580.             shutil.move(file_name, file_name + ".OLDdefault")
  581.         except:
  582.             pass
  583.         f = open(file_name, 'w')
  584.         f.writelines(newliloconf)
  585.         f.close()
  586.         self._logger.log("Lilo installed and configured.  Not run yet.")
  587.         
  588.     def _gather_lilo_drive_info(self):
  589.         self.boot_device = ""
  590.         self.boot_minor = ""
  591.         self.root_device = ""
  592.         self.root_minor = ""
  593.         self.mbr_device = ""
  594.         minornum = 0
  595.         #Assign root to the root mount point to make lines more readable
  596.         root = self._chroot_dir
  597.         self.foundboot = False
  598.         parts = self._install_profile.get_partition_tables()
  599.         for device in parts:
  600.             tmp_partitions = parts[device].get_install_profile_structure()
  601.             for partition in tmp_partitions:
  602.                 mountpoint = tmp_partitions[partition]['mountpoint']
  603.                 if (mountpoint == "/boot"):
  604.                     self.foundboot = True
  605.                 if (( (mountpoint == "/") and (not self.foundboot) ) or (mountpoint == "/boot")):
  606.                     self.boot_minor = str(int(tmp_partitions[partition]['minor']))
  607.                     self.boot_device = device
  608.                     self.mbr_device = device
  609.                 if mountpoint == "/":
  610.                     self.root_minor = str(int(tmp_partitions[partition]['minor']))
  611.                     self.root_device = device
  612.         #RESET the boot device if one is stored already
  613.         if self._install_profile.get_boot_device():
  614.             self.mbr_device = self._install_profile.get_boot_device()
  615.             self._logger.log("Found a mbr device: " + self.mbr_device)            
  616.         
  617.     def _lilo_add_windows(self, newliloconf):
  618.         parts = self._install_profile.get_partition_tables()
  619.         for device in parts:
  620.             tmp_partitions = parts[device].get_install_profile_structure()
  621.             for partition in tmp_partitions:
  622.                 if (tmp_partitions[partition]['type'] == "vfat") or (tmp_partitions[partition]['type'] == "ntfs"):
  623.                     newliloconf += "other="+device+str(int(tmp_partitions[partition]['minor']))+"\n"
  624.                     newliloconf += "label=Windows_P"+str(int(tmp_partitions[partition]['minor']))+"\n\n"
  625.         return newliloconf
  626.         
  627.     def _map_device_to_grub_device(self, device):
  628.         file_name = self._chroot_dir + "/boot/grub/glidevice.map"
  629.         #If we can't find it, make it.  If we STILL can't find it. die.
  630.         if not GLIUtility.is_file(file_name):
  631.             exitstatus1 = GLIUtility.spawn("echo quit | "+ self._chroot_dir+"/sbin/grub --no-floppy --device-map="+file_name)
  632.         if not GLIUtility.is_file(file_name):
  633.             raise GLIException("BootloaderError", 'fatal', '_configure_grub', "Error making the new device map.")
  634.         """
  635.         read the device map.  sample looks like this:
  636.         (fd0)   /dev/floppy/0
  637.         (hd0)   /dev/sda
  638.         (hd1)   /dev/hda
  639.         (hd2)   /dev/hdb
  640.         """
  641.         
  642.         # Search for the key
  643.         f = open(file_name)  #open the device map
  644.         file = f.readlines()
  645.         f.close()    
  646.         for i in range(len(file)):
  647.             if file[i][6:-1] == device:
  648.                 return file[i][1:4]
  649.         raise GLIException("BootloaderError", 'fatal', '_map_device_to_grub_device', "ERROR, could not map"+device+" to anything in the device map")
  650.  
  651.     def setup_and_run_bootloader(self):
  652.         bootloader_pkg = self._install_profile.get_boot_loader_pkg()
  653.         if bootloader_pkg.lower() == "none":
  654.             return
  655.         elif "grub" in bootloader_pkg: # this catches 'grub-static' as well as '=sys-boot/grub-0.95*'
  656.             self._setup_grub()
  657.         elif "lilo" in bootloader_pkg:
  658.             self._setup_lilo()
  659.         # probably should add in some more bootloaders
  660.         # dvhtool, raincoat, netboot, gnu-efi, cromwell, syslinux, psoload
  661.         else:
  662.             raise GLIException("BootLoaderError",'fatal','setup_and_run_bootloader',"Don't know how to configure this bootloader: "+bootloader_pkg)
  663.  
  664.     def _setup_grub(self):
  665.         #-------------------------------------------------------------
  666.         #OK, now that the file is built.  Install grub.
  667.         #cp /proc/mounts /etc/mtab
  668.         #grub-install --root-directory=/boot /dev/hda
  669.         #shutil.copy("/proc/mounts",root +"/etc/mtab")
  670.         self._gather_grub_drive_info()
  671.         grubinstallstring = "echo -en 'root ("+self.grub_boot_drive + "," + self.grub_boot_minor + ")\n"
  672.         if not self._install_profile.get_boot_loader_mbr():
  673.             grubinstallstring +="setup ("+self.grub_boot_drive + "," + self.grub_boot_minor + ")\n"
  674.         else:
  675.             grubinstallstring +="setup ("+self.grub_mbr_drive+")\n"
  676.         grubinstallstring += "quit\n' | "+self._chroot_dir+"/sbin/grub --batch --no-floppy"
  677.         if self._debug: self._logger.log("DEBUG: _configure_grub(): Grub install string: " + grubinstallstring)
  678.         exitstatus = GLIUtility.spawn(grubinstallstring, logfile=self._compile_logfile, append_log=True)
  679.         if not GLIUtility.exitsuccess(exitstatus):
  680.             raise GLIException("GrubInstallError", 'fatal', '_setup_grub', "Could not install grub!")
  681.         self._logger.log("Bootloader: grub has been installed!")
  682.  
  683.     def _setup_lilo(self):
  684.         #-------------------------------------------------------------
  685.         #OK, now that the file is built.  Install lilo.
  686.         exitstatus = GLIUtility.spawn("/sbin/lilo",chroot=self._chroot_dir)
  687.         if exitstatus != 0:
  688.             raise GLIException("LiloInstallError", 'fatal', '_setup_lilo', "Running lilo failed!")
  689.         self._logger.log("Bootloader: lilo has been run/installed!")
  690.